#ifndef __BLOCKQUEUE_H
#define __BLOCKQUEUE_H

#include <deque>
#include <condition_variable>
#include <mutex>
#include <sys/time.h>

template <typename T>
class BlockQueue
{
public:
    // 构造函数
    explicit BlockQueue(size_t maxsize = 1000);

    // 析构函数
    ~BlockQueue();

    // 判断队列是否为空
    bool empty();

    // 判断队列是否已满
    bool full();

    // 将元素插入队列尾部
    void push_back(T &item);

    // 将元素插入队列头部
    void push_back(T &item);

    // 清空队列
    void clear();

    // 返回队列头部元素
    T front();

    // 返回队列尾部元素
    T back();

    // 返回队列容量
    size_t capacity();

    // 返回队列大小
    size_t size();

    // 立即刷新队列（立即将数据写入队列）
    void flush();

    // 关闭队列
    void close();

private:
    // 底层数据结构，存放T类型数据的双向队列
    std::deque<T> deq_;

    // 锁
    std::mutex mtx_;

    // 关闭标志
    bool isClose_;

    // 队列容量
    size_t capacity_;

    // 消费者条件变量
    std::condition_variable condConsumer_;

    // 生产者条件变量
    std::condition_variable condProducer_;
};

// 构造函数
template <typename T>
BlockQueue<T>::BlockQueue(size_t maxsize) : capacity_(maxsize)
{
    assert(maxsize > 0);
    isClose_ = false;
}

template <typename T>
BlockQueue<T>::~BlockQueue()
{
    close();
}

template <typename T>
bool BlockQueue<T>::empty()
{
    std::lock_guard<std::mutex> locker(mtx_);
    return deq_.empty();
}

// 判断队列是否已满
template <typename T>
bool BlockQueue<T>::full()
{
    std::lock_guard<std::mutex> locker(mtx_);
    return deq_.size() >= capacity_;
}

// 将元素插入队列尾部
template <typename T>
void BlockQueue<T>::push_back(T &item)
{
    std::unique_lock<std::mutex> locker(mtx_);
    while (full())
    {
        condProducer_.wait(locker);
    }
    deq_.push_back(item);
    condConsumer_.notify_one();
}

#endif
